package edu.cth.ai23;

import java.util.LinkedList;
import java.util.Queue;
/*
* When trying to solve cubes more than 2-3 moves from the solution, we run out of heap space
*
*/
public class BreadthFirstSearch extends Solver implements IProblemSolver {

    
    public BreadthFirstSearch(IProblem problem) {
        super();
        this.problem = problem.getProblemCopy();
    }

    public void run() {
        solved = false;

        Queue<Integer[]> moves = new LinkedList<Integer[]>();

        moves.add(new Integer[0]);

        long lastTime = System.currentTimeMillis();
        this.timeStarted = lastTime;

        while (!moves.isEmpty() && !this.solved && !this.stop) {
            Integer[] movesListIndexes = moves.remove();

            long nowTime = System.currentTimeMillis();
            lastTime = nowTime;

            problem.moveSequence(movesListIndexes, problem);
            System.out.println("Eval: " + this.problem.evaluate());
            if (problem.evaluate() == 0) { //mean this cube is in a solved state

                synchronized (lock) {
                    this.solved = true;
                }

                timeFinished = System.currentTimeMillis();
                //System.out.println("Found solution, requires moves: ");
                this.report = "Found solution, requires moves:\n";
                for (int j = 0; j < movesListIndexes.length; j++) {
                    //System.out.println("Move " + (j+1) + ": " + Transform.CUBEVALUES[movesListIndexes[j]]);
                    this.report = this.report + "Move " + (j+1) + ": " + problem.getMoveName(movesListIndexes[j]) + "\n";
                }
                break;
            } else {
                Integer[] movesIndexes = problem.getNoOfMoves(-1);
                for (int i = 0; i < movesIndexes.length; i++) {
                    int newMoveIndex = movesIndexes[i];
                    System.out.println("newMoveIndex: " + newMoveIndex);
                    Integer[] newMoves = new Integer[movesListIndexes.length+1];

                    for (int j = 0; j < movesListIndexes.length; j++) {
                        newMoves[j] = movesListIndexes[j];
                    }

                    newMoves[movesListIndexes.length] = newMoveIndex;
                    
                    moves.add(newMoves);

                }
            }

            //Transform.reverseMovesToCube(rc, movesListIndexes);
            problem.reverseMoveSequence(movesListIndexes, problem);
            //System.out.println("Move seq after: " + problem.evaluate());

        }

    }

    public String getName() {
        return "Breadth first, smarter";
    }
}